﻿#include "LETdMessenger.hh"

#include "G4ScoringManager.hh"
#include "G4SystemOfUnits.hh"
#include "G4Tokenizer.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIdirectory.hh"
#include "G4UImanager.hh"
#include "G4VScoringMesh.hh"
#include "PSSDoseAveragedLET.hh"

LETdMessenger::LETdMessenger()
{
    fDir = new G4UIdirectory("/letd/");
    fDir->SetGuidance("Commands for dose-averaged LET (LETd) scoring.");
    //==========
    fAddToMesh = new G4UIcmdWithAString("/letd/addToMesh", this);
    fAddToMesh->SetGuidance("Attach a dose-averaged LET scorer to a scoring mesh.");
    fAddToMesh->SetGuidance("Usage: /letd/addToMesh <meshName> [primitiveName]");

    ///==================== 添加各种位置参数, 调用顺序就是位置顺序
    //========== 参数 0：meshName，必填
    G4UIparameter* meshParam = new G4UIparameter("meshName", 's', false);
    fAddToMesh->SetParameter(meshParam);
    //========== 参数 1：primitiveName，选填，默认 LETd
    G4UIparameter* psParam = new G4UIparameter("primitiveName", 's', true);
    psParam->SetDefaultValue("LETd");
    fAddToMesh->SetParameter(psParam);
}

LETdMessenger::~LETdMessenger()
{
    delete fAddToMesh;
    delete fDir;
}

void LETdMessenger::SetNewValue(G4UIcommand* cmd, G4String val)
{
    ///=============================== /letd/addToMesh 命令
    if (cmd == fAddToMesh) SetNew_LETdAddToMesh(cmd, val);
}

void LETdMessenger::SetNew_LETdAddToMesh(G4UIcommand* cmd, G4String newVal)
{
    // 解析参数：<meshName> [psName]
    // Geant4 已经把两个串拆好，用 # 分隔
    G4Tokenizer tok(newVal);
    G4String meshName = tok();
    G4String psName = tok();  // 若用户没给，这里已经是 "LETd"

    if (meshName.empty() || meshName == "")
    {
        G4Exception("LETdMessenger::SetNewValue", "LETD001", JustWarning, "Missing meshName. Usage: /letd/addToMesh <meshName> [primitiveName]");
        return;
    }

    G4cout << "[LETdMessenger] addToMesh called on " << (G4Threading::IsWorkerThread() ? "WORKER" : "MASTER") << ", mesh=" << meshName
           << ", psName=" << psName << G4endl;

    auto* const scrMgr = G4ScoringManager::GetScoringManagerIfExist();
    if (!scrMgr)
    {
        G4Exception("LETdMessenger::SetNewValue", "LETD002", JustWarning, "G4ScoringManager not found. Did you enable scoring?");
        return;
    }

    //------------------------------- 按名称查找 mesh，并将 primitive 加上去
    G4VScoringMesh* const mesh = scrMgr->FindMesh(meshName);
    if (!mesh)
    {
        G4String msg = "Mesh '" + meshName + "' not found.";
        G4Exception("LETdMessenger::SetNewValue", "LETD003", JustWarning, msg);
        return;
    }

    scrMgr->SetCurrentMesh(mesh);
    G4cout << "[LETdMessenger] Before addToMesh: current mesh = " << (scrMgr->GetCurrentMesh() ? scrMgr->GetCurrentMesh()->GetWorldName() : "NULL")
           << G4endl;

    //----------------- 将 LETd primitive 注册到该 mesh
    if (!mesh->FindPrimitiveScorer(psName))
    {
        auto* const scorer = new PSSDoseAveragedLET(psName);
        mesh->SetPrimitiveScorer(scorer);
        G4cout << "[LETdMessenger] Primitive '" << psName << "' attached to mesh '" << meshName << "'.\n";
    }
}